package com.hankol.winecellar.utils;

import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;

import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

/************************************
 ***        @author zhanglijie       ***
 ***        @date 2020-02-19         ***
 ***                              ***
 ************************************
 */
public abstract class BaseAdapter<VH extends BaseAdapter.ViewHolder> extends RecyclerView.Adapter<VH> {

    /**
     * 上下文对象
     */
    private final Context mContext;

    /**
     * RecycleRView 对象
     */
    private RecyclerView mRecyclerView;

    /**
     * 条目点击事件
     */
    private OnItemClickListener mItemClickListener;
    /**
     * 条目长按事件
     */
    private OnItemLongClickListener mItemLongClickListener;
    /**
     * 条目子 View 点击事件
     */
    private SparseArray<OnChildClickListener> mChildClickListeners;
    /**
     * 条目子 View 长按事件
     */
    private SparseArray<OnChildLongClickListener> mChildLongClickListener;

    /**
     * 滚动监听事件
     */
    private OnScrollingListener mScrollingListener;
    /**
     * 滚动监听器
     */
    private ScrollListener mScrollListener;


    public BaseAdapter(Context mContext) {
        this.mContext = mContext;
        if (mContext == null) {
            throw new IllegalArgumentException("content is null");
        }
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        holder.markViewHolderPosition(position);
        holder.onBindView(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        checkRecyclerViewState();
        this.mItemClickListener = onItemClickListener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
        checkRecyclerViewState();
        this.mItemLongClickListener = onItemLongClickListener;
    }

    public void setOnChildClickListeners(@IdRes int id, OnChildClickListener childClickListener) {
        checkRecyclerViewState();
        if (mChildClickListeners == null) {
            mChildClickListeners = new SparseArray<>();
        }
        this.mChildClickListeners.put(id, childClickListener);
    }

    public void setOnChildLongClickListener(@IdRes int id, OnChildLongClickListener onChildLongClickListener) {
        checkRecyclerViewState();
        if (mChildLongClickListener == null) {
            mChildLongClickListener = new SparseArray<>();
        }
        this.mChildLongClickListener.put(id, onChildLongClickListener);
    }

    /**
     * 设置条目滚动监听
     *
     * @param onScrollingListener
     */
    public void setOnScrollingListener(OnScrollingListener onScrollingListener) {
        this.mScrollingListener = onScrollingListener;
        // 如果当前已经有设置滚动监听，则需要给 RecyclerView 设置监听
        if (mScrollingListener == null) {
            mScrollListener = new ScrollListener();
        } else {
            mRecyclerView.removeOnScrollListener(mScrollListener);
        }
        // 用户设置了滚动监听，需要给 RecyclerView 设置监听
        if (mRecyclerView != null) {
            // 添加滚动监听
            mRecyclerView.addOnScrollListener(mScrollListener);
        }
    }


    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        // 用户设置了滚动监听，需要给 RecyclerView 设置监听
        if (mScrollListener != null) {
            // 添加监听
            mRecyclerView.addOnScrollListener(mScrollListener);
        }

        // 判断当前的布局管理器是否为空，如果为则设置默认的布局管理器
        if (mRecyclerView.getLayoutManager() == null) {
            RecyclerView.LayoutManager layoutManager = generateDefaultLayoutManager(mContext);
            if (layoutManager != null) {
                mRecyclerView.setLayoutManager(layoutManager);
            }
        }
    }

    protected RecyclerView.LayoutManager generateDefaultLayoutManager(Context context) {
        return new LinearLayoutManager(context);
    }

    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        // 移除滚动监听
        if (mScrollListener != null) {
            mRecyclerView.removeOnScrollListener(mScrollListener);
        }
        mRecyclerView = null;
    }

    public Context getContext() {
        return mContext;
    }

    /**
     * 获取 RecyclerView 对象，需要在 setAdapter 之后绑定
     *
     * @return
     */
    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    private void checkRecyclerViewState() {
        if (mRecyclerView != null) {
            throw new IllegalStateException("必须在 RecyclerView.setAdapter() 之前设置监听");
        }
    }

    public interface OnScrollingListener {
        /**
         * 列表滚动到顶部
         *
         * @param recyclerView
         */
        void onScrollTop(RecyclerView recyclerView);

        /**
         * 列表滚动中
         *
         * @param recyclerView
         */
        void onScrolling(RecyclerView recyclerView);

        /**
         * 列表滚动到底部
         *
         * @param recyclerView
         */
        void onScrollBottom(RecyclerView recyclerView);
    }


    /**
     * RecyclerView 条目点击事件
     */
    public interface OnItemClickListener {
        void onItemClick(RecyclerView recyclerView, View itemView, int position);
    }

    /**
     * RecyclerView 条目长按事件
     */
    public interface OnItemLongClickListener {
        boolean onItemLongClick(RecyclerView recyclerView, View itemView, int position);
    }

    /**
     * RecyclerView 条目的子 View 点击事件
     */
    public interface OnChildClickListener {
        void onChildClick(RecyclerView recyclerView, View childView, int position);
    }

    /**
     * RecyclerView 条目的子 View 长按事件
     */
    public interface OnChildLongClickListener {
        boolean onChildLongClick(RecyclerView recyclerView, View childView, int postion);
    }

    private class ScrollListener extends RecyclerView.OnScrollListener {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            if (mScrollingListener == null) {
                return;
            }
            /*
             * 不在滚动状态
             */
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                if (recyclerView.canScrollVertically(1)) {
                    // 是否能向下滚动， false 表示已经滚动都底部
                    mScrollingListener.onScrollBottom(recyclerView);
                } else if (!recyclerView.canScrollVertically(-1)) {
                    // 是否能向上滚动，false 表示已经滚动到顶部
                    mScrollingListener.onScrollTop(recyclerView);
                }
            } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                // 拖拽中
                mScrollingListener.onScrolling(recyclerView);

            }
        }
    }

    public abstract class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
        /**
         * 当前 ViewHolder 位置
         *
         * @param itemView
         */
        private int mViewHolderPosition;

        public ViewHolder(@LayoutRes int id) {
            this(LayoutInflater.from(getContext()).inflate(id, getRecyclerView(), false));
        }

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            // 设置条目的点击和长按事件
            if (mItemClickListener != null) {
                getItemView().setOnClickListener(this);
            }

            if (mItemLongClickListener != null) {
                getItemView().setOnLongClickListener(this);
            }

            if (mChildLongClickListener != null) {
                for (int i = 0; i < mChildLongClickListener.size(); i++) {
                    View child = findViewById(mChildClickListeners.keyAt(i));
                    if (child != null) {
                        child.setOnLongClickListener(this);
                    }
                }
            }

            if (mChildClickListeners != null) {
                for (int i = 0; i < mChildClickListeners.size(); i++) {
                    View child = findViewById(mChildClickListeners.keyAt(i));
                    if (child != null) {
                        child.setOnClickListener(this);
                    }
                }
            }
        }

        /**
         * 初始化 View，可以直接通过 baseAdapter 重写的 findViewById() 来获取 view
         */
        protected abstract void onBindView(int position);

        final void markViewHolderPosition(int position) {
            mViewHolderPosition = position;
        }

        protected final int getViewHolderPosition() {
            return getAdapterPosition();
        }

        @Override
        public void onClick(View v) {
            if (v == getItemView()) {
                if (mItemClickListener != null) {
                    mItemClickListener.onItemClick(mRecyclerView, v, getViewHolderPosition());
                    return;
                }
            }

            if (mChildClickListeners != null) {
                OnChildClickListener listener = mChildClickListeners.get(v.getId());
                if (listener != null) {
                    listener.onChildClick(mRecyclerView, v, getViewHolderPosition());
                }
            }
        }

        @Override
        public boolean onLongClick(View v) {
            if (v == getItemView()) {
                if (mItemLongClickListener != null) {
                    return mItemLongClickListener.onItemLongClick(mRecyclerView, v, getViewHolderPosition());
                }

                if (mChildLongClickListener != null) {
                    OnChildLongClickListener listener = mChildLongClickListener.get(getViewHolderPosition());
                    if (listener != null) {
                        return listener.onChildLongClick(mRecyclerView, v, getViewHolderPosition());
                    }
                }
            }
            return false;
        }

        public final View getItemView() {
            return itemView;
        }

        public final <V extends View> V findViewById(@IdRes int id) {
            return getItemView().findViewById(id);
        }
    }

}
